package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CategoryBasicDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.BooleanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionReplyAdminVo;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.aspectj.weaver.ast.Var;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author hzy
 * @since 2023-09-09
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    private final UserClient userClient;

    private final InteractionReplyMapper replyMapper;

    private final CourseClient courseClient;

    private final SearchClient searchClient;

    private final CategoryClient categoryClient;

    private final CatalogueClient catalogueClient;

    private final CategoryCache categoryCache;

    /**
     * 新增互动问题(用户端)
     *
     * @param questionFormDTO
     */
    @Override
    public void addInteractionQuestions(QuestionFormDTO questionFormDTO) {
        Long userId = UserContext.getUser();
        InteractionQuestion interactionQuestion = BeanUtils.copyBean(questionFormDTO, InteractionQuestion.class);
        interactionQuestion.setUserId(userId);
        save(interactionQuestion);
    }

    /**
     * 分页查询问题(用户端)
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> selectPage(QuestionPageQuery query) {
        if (query.getCourseId() == null && query.getSectionId() == null) {
            throw new BizIllegalException("参数有误,CourseId和SectionId不能同时为空");
        }
        Long userId = UserContext.getUser();

        Page<InteractionQuestion> page = new Page<>(query.getPageNo(), query.getPageSize());
        lambdaQuery().eq(BooleanUtils.isTrue(query.getOnlyMine()), InteractionQuestion::getUserId, userId)  //Boolean可能为null
                .select(InteractionQuestion.class, tableFieldInfo -> !tableFieldInfo.getProperty().equals("description")) //不查 description
                .eq(InteractionQuestion::getHidden, false)
                .eq(query.getCourseId() != null, InteractionQuestion::getCourseId, query.getCourseId())
                .eq(query.getSectionId() != null, InteractionQuestion::getSectionId, query.getSectionId())
                .page(page);
        List<InteractionQuestion> questions = page.getRecords();
        if (CollUtils.isEmpty(questions)) {
            return PageDTO.empty(page);
        }

        List<Long> userIds = questions.stream().map(InteractionQuestion::getUserId).collect(Collectors.toList());
        //查询最新一个提问者
        List<Long> answerIds = questions.stream().map(InteractionQuestion::getLatestAnswerId).collect(Collectors.toList());
        Map<Long, InteractionReply> replyMap = new HashMap<>();
        if (CollUtils.isNotEmpty(answerIds)) {
            List<InteractionReply> replyList = replyMapper.selectBatchIds(answerIds);
            replyMap = replyList.stream().filter(Objects::nonNull)
                    .collect(Collectors.toMap(InteractionReply::getId, interactionReply -> interactionReply));
        }
        //将需要的用户id存入集合
        Collections.copy(userIds, new ArrayList<>(replyMap.keySet()));

        //查询用户信息
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (CollUtils.isNotEmpty(userIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userMap = userDTOS.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(UserDTO::getId, userDTO -> userDTO));
        }

        List<QuestionVO> listVo = new ArrayList<>();
        for (InteractionQuestion question : questions) {
            QuestionVO questionVO = BeanUtils.copyBean(question, QuestionVO.class);
            if (!question.getHidden()) {
                //封装
                UserDTO userDTO = userMap.get(question.getUserId());
                //匿名不需要返回用户信息
                if (userDTO != null && !question.getAnonymity()) {
                    questionVO.setUserName(userDTO.getName());
                    questionVO.setUserIcon(userDTO.getIcon());
                }

                InteractionReply reply = replyMap.get(question.getLatestAnswerId());
                if (reply != null) {
                    questionVO.setLatestReplyContent(reply.getContent());
                    //匿名的不查
                    if (!reply.getAnonymity()) {
                        UserDTO replyDto = userMap.get(reply.getUserId());
                        if (replyDto != null) {
                            questionVO.setLatestReplyUser(replyDto.getName());
                        }
                    }
                }
                listVo.add(questionVO);
            }
        }

        return PageDTO.of(page, listVo);
    }

    /**
     * 根据id查询问题详情(用户端)
     *
     * @param id
     * @return
     */
    @Override
    public QuestionVO selectDescriptionById(Long id) {
        //查询问题
        InteractionQuestion interactionQuestion = getById(id);
        if (interactionQuestion == null) {
            throw new DbException("查询的问题不存在!!!");
        }
        QuestionVO questionVO = BeanUtils.copyBean(interactionQuestion, QuestionVO.class);

        //匿名不查
        if (!interactionQuestion.getAnonymity()) {
            Long userId = interactionQuestion.getUserId();
            if (userId != null) {
                //查询用户信息
                UserDTO userDTO = userClient.queryUserById(userId);
                if (userDTO != null) {
                    questionVO.setUserName(userDTO.getName());
                    questionVO.setUserIcon(userDTO.getIcon());
                }
            }
        }
        return questionVO;
    }

    /**
     * 分页查询问题(管理端)
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> selectAdminPage(QuestionAdminPageQuery pageQuery) {
        Integer pageNo = pageQuery.getPageNo();
        Integer pageSize = pageQuery.getPageSize();
        String courseName = pageQuery.getCourseName();
        Integer status = pageQuery.getStatus();
        LocalDateTime beginTime = pageQuery.getBeginTime();
        LocalDateTime endTime = pageQuery.getEndTime();

        //查询 CourseName 相似课程
        List<Long> courseIds = new ArrayList<>();
        if (courseName != null) {
            //--方法一>>>mysql查询

            //--方法二>>>elasticsearch查询
            courseIds = searchClient.queryCoursesIdByName(courseName);
            if (CollUtils.isEmpty(courseIds)) {
                return PageDTO.empty(0L, 0L);
            }
        }

        //分页查询
        Page<InteractionQuestion> page = new Page<>(pageNo, pageSize);
        lambdaQuery()
                .in(CollUtils.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(status != null, InteractionQuestion::getStatus, status)
                .ge(beginTime != null, InteractionQuestion::getCreateTime, beginTime)
                .le(endTime != null, InteractionQuestion::getCreateTime, endTime)
                .page(page);
        List<InteractionQuestion> questions = page.getRecords();
        if (CollUtils.isEmpty(questions)) {
            return PageDTO.empty(page);
        }

        List<Long> userIds = questions.stream().map(InteractionQuestion::getUserId).collect(Collectors.toList());
        Map<Long, String> userMap = new HashMap<>();
        if (CollUtils.isNotEmpty(userIds)) {
            //查询用户信息
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        }

        //查询课程名称,三级分类
        List<Long> courseIdList = questions.stream().map(InteractionQuestion::getCourseId).collect(Collectors.toList());
        Map<Long, String> courseNamesMap = new HashMap<>();
        Map<Long, String> categoryNameMap = new HashMap<>();
        if (CollUtils.isNotEmpty(courseIdList)) {
            List<CourseSimpleInfoDTO> simpleInfoDTOS = courseClient.getSimpleInfoList(courseIdList);
            courseNamesMap = simpleInfoDTOS.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, CourseSimpleInfoDTO::getName));

            List<CategoryBasicDTO> categoryBasicDTOList = categoryClient.getAllOfOneLevel();
            Map<Long, String> basicMap = categoryBasicDTOList.stream().collect(Collectors.toMap(CategoryBasicDTO::getId, CategoryBasicDTO::getName));

            if (CollUtils.isNotEmpty(basicMap)) {
                for (CourseSimpleInfoDTO simpleInfoDTO : simpleInfoDTOS) {
                    Long courseId = simpleInfoDTO.getId();
                    //分类id
                    Long firstCateId = simpleInfoDTO.getFirstCateId();
                    Long secondCateId = simpleInfoDTO.getSecondCateId();
                    Long thirdCateId = simpleInfoDTO.getThirdCateId();
                    String categoryName = "";
                    if (firstCateId != 0 || secondCateId != 0 || thirdCateId != 0) {
                        //分类名称
                        String one = basicMap.get(firstCateId);
                        String two = basicMap.get(secondCateId);
                        String three = basicMap.get(thirdCateId);
                        categoryName = one + "/" + two + "/" + three;
                    }
                    categoryNameMap.put(courseId, categoryName);
                }
            }
        }

        //查询课程章节名称  收集所以id --> 查询名称
        Set<Long> chapterIds = questions.stream().map(InteractionQuestion::getChapterId).collect(Collectors.toSet());
        Set<Long> sectionIds = questions.stream().map(InteractionQuestion::getSectionId).collect(Collectors.toSet());
        Set<Long> allIds = Stream.concat(chapterIds.stream(), sectionIds.stream()).collect(Collectors.toSet());

        List<CataSimpleInfoDTO> simpleInfoDTOS = catalogueClient.batchQueryCatalogue(allIds);
        Map<Long, String> cateMap = simpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));

        List<QuestionAdminVO> vos = new ArrayList<>();
        for (InteractionQuestion question : questions) {
            QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
            //封装
            vo.setUserName(userMap.get(question.getUserId()));
            vo.setCourseName(courseNamesMap.get(question.getCourseId()));
            vo.setChapterName(cateMap.get(question.getChapterId()));
            vo.setSectionName(cateMap.get(question.getSectionId()));
            vo.setCategoryName(categoryNameMap.get(question.getCourseId()));
            vos.add(vo);
        }
        return PageDTO.of(page, vos);
    }

    /**
     * 根据id查询问题详情(管理端)
     *
     * @param id
     * @return
     */
    @Override
    public QuestionReplyAdminVo selectDetailById(Long id) {
        InteractionQuestion interactionQuestion = getById(id);
        if (interactionQuestion == null) {
            throw new DbException("问题不存在!!!");
        }
        if (interactionQuestion.getStatus() == QuestionStatus.UN_CHECK) {
            interactionQuestion.setStatus(QuestionStatus.CHECKED);
        }
        updateById(interactionQuestion);
        QuestionReplyAdminVo vo = BeanUtils.copyBean(interactionQuestion, QuestionReplyAdminVo.class);
        //userId查看提问者姓名,提问者头像
        UserDTO userDTO = userClient.queryUserById(interactionQuestion.getUserId());
        vo.setUserName(userDTO.getName());
        vo.setIcon(userDTO.getIcon());

        //获取章, 节 信息
        Long chapterId = interactionQuestion.getChapterId();
        Long sectionId = interactionQuestion.getSectionId();
        List<CataSimpleInfoDTO> dtos = catalogueClient.batchQueryCatalogue(List.of(chapterId, sectionId));
        Map<Long, String> map = dtos.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        vo.setChapterName(map.get(chapterId));
        vo.setSectionName(map.get(sectionId));

        //courseId查询课程名字,三级目录,教师名字 coures_teacher_draft表
        CourseFullInfoDTO courseInfoById = courseClient.getCourseInfoById(interactionQuestion.getCourseId(), true, true);
        if (courseInfoById == null) {
            return vo;
        }
        Long firstCateId = courseInfoById.getFirstCateId();
        Long secondCateId = courseInfoById.getSecondCateId();
        Long thirdCateId = courseInfoById.getThirdCateId();
        List<Long> teacherIds = courseInfoById.getTeacherIds();

        String categoryNames = categoryCache.getCategoryNames(List.of(firstCateId, secondCateId, thirdCateId));

        if (CollUtils.isNotEmpty(teacherIds)) {
            List<UserDTO> userDTOS = userClient.queryUserByIds(teacherIds);
            if (CollUtils.isNotEmpty(userDTOS)) {
                for (UserDTO dto : userDTOS) {
                    String name = dto.getName();
                    if (name != null) {
                        vo.setTeacherName(name);
                        break;
                    }
                }
            }
        }

        vo.setCourseName(courseInfoById.getName());
        vo.setCategoryName(categoryNames);

        return vo;
    }

    /**
     * 修改互动问题(用户端)
     *
     * @param id
     * @param dto
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO dto) {
        boolean update = lambdaUpdate().eq(InteractionQuestion::getId, id)
                .set(InteractionQuestion::getTitle, dto.getTitle())
                .set(InteractionQuestion::getDescription, dto.getDescription())
                .set(InteractionQuestion::getAnonymity, dto.getAnonymity())
                .update();
        if (!update) {
            throw new DbException("修改互动问题失败!!!");
        }
    }
}
